<?php

/**
 * 阿里云短信服务
 * @author Wangfy
 * @date 2019年7月22日
 * @copyright 链盟科技
 */
header("Content-type:text/html; charset=UTF-8");

final class ectools_messenger_plugin_alisms extends ectools_messenger_app implements ectools_interface_messenger_app {

    /**
     * @var string 短信平台名称
     */
    public $name = '阿里云短信服务';

    /**
     * @var string 短信平台接口名称
     */
    public $sms_name = '阿里云短信服务接口';

    /**
     * @var string 短信平台key
     */
    public $app_key = 'alisms';

    /**
     * @var string 中心化统一的key
     */
    public $app_rpc_key = 'alisms';

    /**
     * @var string 统一显示的名称
     */
    public $display_name = '阿里云短信';

    public function __construct() {
        $this->httpClient = kernel::single('base_httpclient');
        $this->httpClient->set_timeout(6);
    }

    /**
     * 短信平台的简介
     * @param null
     * @return string 简介内容
     */
    public function getSmsbrief() {
        return app::get('ectools')->_('阿里云-短信服务');
    }

    /**
     * 短信平台的参数设置
     * @param null
     * @return array 配置参数列表
     */
    public function setting() {
        return array(
            'sms_name' => array(
                'title' => app::get('ectools')->_('短信平台名称'),
                'type' => 'string',
                'validate_type' => 'required'
            ),
            'sms_apiurl' => array(
                'title' => app::get('ectools')->_('短信接口地址'),
                'type' => 'string',
                'validate_type' => 'required'
            ),
            'accesskeyid' => array(
                'title' => app::get('ectools')->_('AccessKeyId'),
                'type' => 'string',
                'validate_type' => 'required'
            ),
            'accesskeysecret' => array(
                'title' => app::get('ectools')->_('AccessKeySecret'),
                'type' => 'string',
                'validate_type' => 'required'
            ),
            'sms_memo' => array(
                'title' => app::get('ectools')->_('备注'),
                'type' => 'textarea'
            ),
            'sms_status' => array(
                'title' => app::get('ectools')->_('是否开启此短信平台'),
                'type' => 'radio',
                'options' => array(
                    'false' => app::get('ectools')->_('否'),
                    'true' => app::get('ectools')->_('是')
                )
            )
        );
    }

    /**
     * 发送短信
     * @params array  $contents  短信内容,按照模板变量组织等同结构的参数
     * @params string $phone     参数为getOptions取得的所有项的配置结果
     * @params string $tmpl_code 模板Code
     * @params string $msg       msg，用于异常返回
     * @return boolean
     * @author Wangfy
     * @date   2019/07/24
     */
    public function sendSms($contents, $phone, $tmpl_code, &$msg) {
        if (! $contents) {
            $msg = app::get('ectools')->_('手机短信不能为空！');
            return false;
        }
        if (! $tmpl_code) {
            $msg = app::get('ectools')->_('短信模板Code不能为空！');
            return false;
        }
        $templateParam = json_encode($contents);
        // 获取通道信息
        $alismsInfo = unserialize(app::get('ectools')->getConf('ectools_messenger_plugin_alisms'));
        if ($alismsInfo['setting']) {
            $sendUrl = $alismsInfo['setting']['sms_apiurl'];
            $accessKeyId = $alismsInfo['setting']['accesskeyid'];
            $accessKeySecret = $alismsInfo['setting']['accesskeysecret'];
            // 注意使用GMT时间
            date_default_timezone_set("GMT");
            $data = array(
                'AccessKeyId' => $accessKeyId,
                'Action' => 'SendSms',
                'Format' => 'JSON',
                // 外部流水扩展字段 可选
                'OutId' => '123',
                // 短信接收号码
                'PhoneNumbers' => $phone,
                'RegionId' => 'cn-hangzhou',
                // 短信签名
                'SignName' => '助功者',
                'SignatureMethod' => 'HMAC-SHA1',
                'SignatureNonce' => uniqid(),
                'SignatureVersion' => '1.0',
                // 短信模板ID
                'TemplateCode' => $tmpl_code,
                // 短信模板变量替换JSON串,
                'TemplateParam' => $templateParam,
                'Timestamp' => date('Y-m-d\TH:i:s\Z'),
                'Version' => '2017-05-25'
            );
            $data['Signature'] = $this->computeSignature($data, $accessKeySecret);
            $result = $this->httpClient->post($sendUrl, $data);
            $res = json_decode($result, true); // json字符串转数组
            if ($res['Message'] == 'OK') {
                $msg = app::get('ectools')->_('短信发送成功！');
                return 'success';
            } else {
                $msg = $result;
                return false;
            }
        } else {
            $msg = app::get('ectools')->_('短信平台尚未配置！');
            return false;
        }
    }

    function percentEncode($str) {
        // 使用urlencode编码后，将"+","*","%7E"做替换即满足ECS API规定的编码规范
        $res = urlencode($str);
        $res = preg_replace('/\+/', '%20', $res);
        $res = preg_replace('/\*/', '%2A', $res);
        $res = preg_replace('/%7E/', '~', $res);
        return $res;
    }

    function computeSignature($parameters, $accessKeySecret) {
        // 将参数Key按字典顺序排序
        ksort($parameters);
        // 生成规范化请求字符串
        $canonicalizedQueryString = '';
        foreach ($parameters as $key => $value) {
            $canonicalizedQueryString .= '&' . $this->percentEncode($key) . '=' . $this->percentEncode($value);
        }
        // 生成用于计算签名的字符串 stringToSign
        $stringToSign = 'POST&%2F&' . $this->percentEncode(substr($canonicalizedQueryString, 1));
        // 计算签名，注意accessKeySecret后面要加上字符'&'
        $signature = base64_encode(hash_hmac('sha1', $stringToSign, $accessKeySecret . '&', true));
        return $signature;
    }
}